iOS tableview重用 tableview重用机制

您所在的位置:网站首页 ios tableview重用机制 iOS tableview重用 tableview重用机制

iOS tableview重用 tableview重用机制

2024-07-12 01:22| 来源: 网络整理| 查看: 265

dequeueResableCellWithIdentifier方法

//对table view的数据进行绑定,即填充cell,自动调用n次

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell*cell = [tableView dequeueReusableCellWithIdentifier:@"FlipsideCellIdentifier"]; if (cell== nil) { cell =[[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:@"FlipsideCellIdentifier"] autorelease]; } cell.text= [soundSignatures objectAtIndex:indexPath.row]; return cell; }

理解:

每一个UITableView里都维护着一个cell队列,当UITableView刚加载的时候,cell队列里是没有任何数据的。

dequeueResableCellWithIdentifier从字面上理解就是"出列可重用的cell", 也就是根据一个标识identifier从cell队列里取出一个UITableViewCell, 当然了,如果cell队列里没有此标识的cell,调用此方法的结果就是返回nil。

因此,在UITableView刚加载的时候,cell队列里没有可用的cell,所以必须通过语句

cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];

来创建对应CellIdentifier标识的UITableViewCell实例。

[ tableView:cellForRowAtIndexPath:方法主要是根据NSIndex取得一个cell ]

而当UITableView在滚动的时候导致UITableViewCell滚出手机屏幕视图的时候,

程序会将这一个UITalbeViewCell实例放入此UITableView所维护的cell队列中。

当UITableview中有新的UITableViewCell需要展现在手机屏幕视图上时,

就会调用tableView:cellForRowAtIndexPath:方法了。

因此我们可以知道以下几点:

1-重取出来的cell是有可能已经捆绑过数据或者加过子视图的,所以,

如果有必要,要清除数据(比如textlabel的text)和remove掉add过的子视图(使用tag)。

2-这样设计的目的是为了避免频繁的 alloc和delloc cell对象而已,没有多复杂。

3-设计的关键是实现cell和数据的完全分离

如果不想重用UITableViewCell实例,如在一个每一行都显示不同内容的UITableView实例时,我们可以用如下的方法:

NSString *CellIdentifier = [NSString stringWithFormat:@"Cell%d%d",[indexPath section], [indexPath row]];

来重新定义标识。

这样每一行都有其对应的identifier,从cell队列里取出来只有两个结果:

1-cell队列里没有此identifier对应的UITableViewCell实例,返回nil

2-cell队列里有此identifier对应的UITableViewCell实例,而且不会有重用到其他不同行的cell的情况

iphone重用机制是苹果为了实现大量数据显示而采用的一种节省内存的机制,比如在UITableView和ScrollView 等地方。为什么要“可重用”???对于我们的项目来说,内存控制是必不可少的,如果一个tableview有几百个cell,这个内存消耗是很大的,而且有些cell里面都有image之类的很占内存的资源存在的话,那这样很容易出现memory warning甚至crash掉,这不是我们想要看到的。对此,tableview实现了它自己的管理方法dequeueReusableCellWithIdentifier(ps:我们在某些项目中scrollview来显示很多张image,在scrollview滑动中也要这样处理,来避免内存的过度消耗,只不过tableview它已经实现了这个方法,而不用我们自己去写)。

 

但是在实际使用过程中,会有以下问题:

1、(苹果文档中不鼓励我们在UITableViewCell中添加subView,最好采用自定义Cell,将需要的SubView添加到Cell当中。)使用addSubView在每项上添加视图的时候会有重叠的现象。例如,UITableView中的Cell ,如果在cell上添加子视图,则在使用苹果的重用机制的时候,会重现子试图重叠的现象。或出现开头提到的两个问题。如果在数据量不是很多的时候,可以手动屏蔽掉UITableView的重用机制。

这里不得不提一下UITableView的重用机制:

 

UITableView的重用机制的实现关键在于下面这个的函数:

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

首先,我们要清楚这一点,这个函数是做什么的,它的文档说明如下:
returns a reusable table-view cell object located by its identifier。它返回的是一个受identifier管理定位的可重用的tableViewCell,这里重点就在于“可重用”这3个字上。

我们来看它的实现方法,举个例子来说,在系统刚启动时,tableview可以显示多少个cell,在这里我们假定为10个,在刚开始的时候tableview会生成10个tableviewcell,并且对应有自己的tag值,假定为0-9。(ps:苹果官方的视频中也提到了,尽量避免频繁的add/remove view或者控件之类等。自定义啊自定义,相对于Android 空间的自定义,)所以采用下面的方法来实现:在tableview向上滚动的时候,tag为0的cell将不再显示;然后我们把tag为0的cell移动到tag为9的cell下面,重新设置相关的属性,然后将tag为1的cell移动到tag为0的cell下面……依此类推。这也就是所谓的“可重用”。

但是此时被移动的tag为0的cell的一些属性还是保持不变的(包括之前添加的subView),因此就会出现一些无厘头的bug(看了这么多,到这里是不是松了口气? )。

 

接下来我们就要使用多种的方法来干掉这个重用机制:          

(1):  

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; if (cell != nil) { [cell release]; //怎么样?? 换了位置的Cell嚣张不了了吧.... }

(2):和(1)的方法本质一样,略显啰嗦。

UITableViewCell *cell =[tableView dequeueReusableCellWithIdentifier:CellIdentifier]; if (cell == nil) { cell = [[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]autorelease]; } NSArray*subviews = [[NSArray alloc]initWithArray:cell.contentView.subviews]; for (UIView *subview in subviews) { [subview removeFromSuperview]; } [subviews release];

(3)://组别都不一样,看你怎么重用。

NSString *CellIdentifier = [NSString stringWithFormat:@"cell%d",indexPath.row];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
........
} else {
return cell;
}

虽然干掉了重构机制,但我还是时不时地会想念它,特别是在数据多的时候,使用重用机制会好对你的程序的内存使用和优化都有很重要的作用。 但是这样的话,如果想再cell上添加东西的话,重叠现象会很严重。好吧,鱼和熊掌捆绑销售啦啦!!使用xib给cell添加视图来添加视图吧......

具体步骤:

(1)新建一个基于UITableViewCell的类A和一个空白的xib。

(2)在A类中声明要添加的视图,例如IBOutlet UILabel *nameLabel,*timeLabel; ,注意:一要是使用  IBOutlet。

(3)将xib中的view删除,拖一个 UITableViewCell,然后将这个UITableViewCell的类改为基于A。再把相应的视图添在UITableViewCell上,并且与A类内定义的变量进行连接。这样准备工作就完成了。

(4)使用方法:

A* cell = (A*)[tableView dequeueReusableCellWithIdentifier:CellIdentifier]; if (cell == nil) { NSArray* nib = [[NSBundle mainBundle] loadNibNamed:@"VideoCell" owner:self options:nil]; cell = [nib objectAtIndex:0]; }

           然后只需在下面改变cell相应视图的属性就可以了。

补充:在使用地图MKMapView一会使用到重用机制,如果想要在MKPinAnnotationView添加视图的话,最好放弃那个重用机制,要不然效果会乱七八糟的(估计还有更好的处理方法)~~

 

    什么,你不喜欢用Xib?好吧,这个老外写的UITableView的代码,估计会合你的口味,实现方式如下:

    1、cell中的释放

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; if (cell == nil) { cell = [[[UITableViewCell alloc] init....] autorelease]; UITextField *field = ...;//初始化 [cell addSubView:field];//添加 [field release];//释放 } 2、通过遍历修改UILabel属性 UITextField*field = nil; for(UIView *v in cell.contentView.subviews) { if([v isMemberOfClass:[UILabel class]]) field = (UITextField *)v; } ......//接下来修改field的属性



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3